package com.simple.datax.flow.convertor;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import net.easipay.ec.v2.ECDataType;
import net.easipay.ec.v2.ECFlow201Document;
import net.easipay.ec.v2.ECFlow201Document.ECFlow201;
import net.easipay.ec.v2.ECFlow201ResponseDocument;
import net.easipay.ec.v2.ECFlow201ResponseDocument.ECFlow201Response;
import net.easipay.ec.v2.ECFlow201ResponseDocument.ECFlow201Response.ResponseHead;
import net.easipay.ec.v2.ECFlow201ResponseDocument.ECFlow201Response.ResponseList;
import net.easipay.ec.v2.ECFlow201ResponseDocument.ECFlow201Response.ResponseList.ActionResult;
import net.easipay.ec.v2.ECFlowType;
import net.easipay.ec.v2.ECFlowType.ActionList;
import net.easipay.ec.v2.ECUserType;

import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.XmlValidationError;

import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.simple.datax.flow.constants.ProcessResultConstants;
import com.simple.datax.flow.message.BaseEcMessage;
import com.simple.datax.flow.message.EcFlowMessage;
import com.simple.datax.flow.message.EcFlowMessageBody;
import com.simple.datax.flow.message.EcFlowMessageHead;
import com.simple.datax.flow.message.EcFlowRespMessage;
import com.simple.datax.flow.message.EcFlowRespMessageBody;
import com.simple.datax.flow.message.EcFlowRespMessageBody.ECFlowResponseHead;
import com.simple.datax.flow.message.EcFlowRespMessageBody.ResponseActionResult;
import com.simple.datax.flow.message.EcFlowRespMessageHead;
import com.simple.datax.flow.util.DateUtil;
import com.simple.datax.utils.SimpleConstants;
import com.simple.datax.xml.ec.EC101MessageDocument;
import com.simple.datax.xml.ec.EC101MessageDocument.EC101Message;
import com.simple.datax.xml.ec.EC101ResponseDocument;
import com.simple.datax.xml.ec.MessageHeadDocument.MessageHead;
import com.simple.datax.xml.ec.XMLDATA;
import com.simple.datax.xml.ec.impl.EC101MessageDocumentImpl;
import com.simple.datax.xml.ec.impl.EC101ResponseDocumentImpl;
/** 
 * @Title: EcMessageConvertor.java 
 * @Package com.simple.datax.flow.convertor 
 * @Description: TODO(报文序列化和反序列化) 
 * @author tonney 
 * @date 2013-1-6 下午05:06:01 
 * @version V1.0 
 */
public class EcMessageConvertor implements Convertor {
	public Logger log = LoggerFactory.getLogger(this.getClass());

	public BaseEcMessage convert2EcMessage(String xml) {
		BaseEcMessage ecMessage = null;
		try {
			XmlObject xmlObj = null;
			if (!xml.startsWith("<")) {
				int beginIndex = xml.indexOf("<");
				if(beginIndex>=0){
					xml = xml.substring(beginIndex);
				}
			}
			xmlObj = XmlObject.Factory.parse(xml);
 			if(xmlObj instanceof EC101MessageDocumentImpl){
				ecMessage  = convert2EcFlowMessage(xmlObj);
			}else if(xmlObj instanceof EC101ResponseDocumentImpl){
				ecMessage = convert2EcFlowRespMessage(xmlObj);
			}else{
				log.warn("EcMessageConvertor::convert2EcMessage unknown message!");
			}
		} catch (Exception e) {
			log.error("EcMessageConvertor::convert2EcMessage error=>"+e.toString());
		}
		return ecMessage;
	}
	
	public BaseEcMessage convert2EcFlowMessage(XmlObject xmlObj){
		String xml = "";
		int result = ProcessResultConstants.STATUS_SUCCESS;
		try{
			EC101MessageDocument ecmessagedoc = (EC101MessageDocument)xmlObj;
			MessageHead  messageHeadDocument = ecmessagedoc.getEC101Message().getMessageHead();
			if(messageHeadDocument!=null){
				xml = ecmessagedoc.getEC101Message().getMessageBody()
						.xmlText().toString();
				XmlObject xmlobj = XmlObject.Factory.parse(xml);
				if (ECFlow201Document.class.isInstance(xmlobj)) {
					EcFlowMessageBody ecMessageFlowBody = new EcFlowMessageBody();
					result = this.convert2EcFlowMessageBody(xmlobj,ecMessageFlowBody);
					if (result == ProcessResultConstants.STATUS_SUCCESS) {
						EcFlowMessageHead ecMessageHead = new EcFlowMessageHead();
						ecMessageHead.setMessageType(messageHeadDocument.getMessageType());
						ecMessageHead.setMessageId(messageHeadDocument.getMessageId());
						ecMessageHead.setMessageTime(DateUtil.getCurTime());
						ecMessageHead.setReceiverAddress(messageHeadDocument.getReceiverAddress());
						ecMessageHead.setReceiverId(messageHeadDocument.getReceiverId());
						ecMessageHead.setSenderAddress(messageHeadDocument.getSenderAddress());
						ecMessageHead.setSenderId(messageHeadDocument.getSenderId());
						EcFlowMessage ecMessage = new EcFlowMessage();
						ecMessage.setOrgSendId(ecMessageHead.getSenderId());
						ecMessage.setOrgSendAddr(ecMessageHead.getSenderAddress());
						ecMessage.setFlowMessageHead(ecMessageHead);
						ecMessage.setFlowMessageBody(ecMessageFlowBody);
						return ecMessage;
					} else {
						log.error("EcMessageConvertor::convert2EcFlowMessage error==>报文转换出错,丢弃报文MessageID["
								+ ecmessagedoc.getEC101Message().getMessageHead()
										.getMessageId() + "]");
					}
				}else if (ECFlow201ResponseDocument.class.isInstance(xmlobj)) {
					EcFlowRespMessageBody ecMessageFlowRespBody = new EcFlowRespMessageBody();
					result = this.convert2EcFlowRespMessageBody(xmlobj,ecMessageFlowRespBody);	
					if (result == ProcessResultConstants.STATUS_SUCCESS) {
						EcFlowRespMessageHead respMessageHead = new EcFlowRespMessageHead();
						respMessageHead.setMessageType(messageHeadDocument.getMessageType());
						respMessageHead.setMessageId(messageHeadDocument.getMessageId());
						respMessageHead.setMessageTime(DateUtil.getCurTime());
						respMessageHead.setReceiverAddress(messageHeadDocument.getReceiverAddress());
						respMessageHead.setReceiverId(messageHeadDocument.getReceiverId());
						respMessageHead.setSenderAddress(messageHeadDocument.getSenderAddress());
						respMessageHead.setSenderId(messageHeadDocument.getSenderId());
						EcFlowRespMessage ecRespMessage = new EcFlowRespMessage();
						ecRespMessage.setOrgSendId(respMessageHead.getSenderId());
						ecRespMessage.setOrgSendAddr(respMessageHead.getSenderAddress());
						ecRespMessage.setFlowRespMessageHead(respMessageHead);
						ecRespMessage.setFlowRespMessageBody(ecMessageFlowRespBody);
						return ecRespMessage;
					} else {
						log.error("EcMessageConvertor::convert2EcFlowMessage error==>报文转换出错,丢弃报文MessageID["
								+ ecmessagedoc.getEC101Message().getMessageHead()
										.getMessageId() + "]");
					}
				}
			}
		}catch(Exception e){
			result = ProcessResultConstants.STATUS_XSD_PARSE_FAILURE;
			log.error("EcMessageConvertor::convert2EcMessage error=>"+e.toString());
		}
		return null;
	}
	
	public BaseEcMessage convert2EcFlowRespMessage(XmlObject xmlObj){
		String ecflow = "";
		EcFlowRespMessageHead ecRespMessageHead = null;
		int result = ProcessResultConstants.STATUS_SUCCESS;
		EcFlowRespMessage ecRespMessage = null;
		try{
			EC101ResponseDocument ecRespMessagedoc = (EC101ResponseDocument)xmlObj;
			MessageHead  messageHeadDocument = ecRespMessagedoc.getEC101Response().getMessageHead();
			if(messageHeadDocument!=null){
				ecRespMessageHead = new EcFlowRespMessageHead();
				ecRespMessageHead.setMessageType(messageHeadDocument.getMessageType());
				ecRespMessageHead.setMessageId(messageHeadDocument.getMessageId());
				ecRespMessageHead.setMessageTime(DateUtil.getCurTime());
				ecRespMessageHead.setReceiverAddress(messageHeadDocument.getReceiverAddress());
				ecRespMessageHead.setReceiverId(messageHeadDocument.getReceiverId());
				ecRespMessageHead.setSenderAddress(messageHeadDocument.getSenderAddress());
				ecRespMessageHead.setSenderId(messageHeadDocument.getSenderId());
			}
			ecflow = ecRespMessagedoc.getEC101Response().getMessageBody()
					.xmlText().toString();
			EcFlowRespMessageBody ecMessageFlowRespBody = new EcFlowRespMessageBody();
			ecRespMessage = new EcFlowRespMessage();
			ecRespMessage.setFlowRespMessageHead(ecRespMessageHead);
		}catch(Exception e){
			result = ProcessResultConstants.STATUS_XSD_PARSE_FAILURE;
			log.error("EcMessageConvertor::convert2EcMessage error=>"+e.toString());
		}
		return ecRespMessage;
	}

	public int convert2EcFlowMessageBody(XmlObject xmlobj,EcFlowMessageBody messageBody) throws Exception {
		int result = ProcessResultConstants.STATUS_SUCCESS;
		try{
			if (ECFlow201Document.class.isInstance(xmlobj)) {
				ECFlow201Document ecFlow201Document = (ECFlow201Document) xmlobj;
				ECFlow201 ecFlow201 = ecFlow201Document.getECFlow201();
				if (ecFlow201.getECUser() != null) {
					messageBody.setUserId(ecFlow201.getECUser().getUserId());
					messageBody.setUserPrivateKey(ecFlow201.getECUser()
							.getUserPrivateKey());
				}
				if (ecFlow201.getECFlow() != null) {
					messageBody.setMessageId(ecFlow201.getECFlow().getMessageId());
					messageBody.setFlowId(ecFlow201.getECFlow().getBpNo());
					if (ecFlow201.getECFlow().getActionList() != null
							&& ecFlow201.getECFlow().getActionList()
									.getActionIdArray().length > 0) {
						String[] actionIdArray = ecFlow201.getECFlow()
								.getActionList().getActionIdArray();
						if(actionIdArray!=null){
							for (String actionId : actionIdArray) {
								messageBody.getActivityIdList().add(actionId);
							}
						}
					}
					messageBody.setTaskId(ecFlow201.getECFlow().getTaskId());
					messageBody.setTaskNote(ecFlow201.getECFlow().getTaskNote());
					messageBody.setCorpTaskId(ecFlow201.getECFlow().getCorpTaskId());
					messageBody.setTaskControl(ecFlow201.getECFlow()
							.getTaskControl());
					messageBody.setEcData(ecFlow201.getECData());	
				}
				if (ecFlow201.isSetECData()
						&& ecFlow201.getECData().getDomNode().getFirstChild() != null) {
					messageBody.setEcData(ecFlow201.getECData());
				}
			}else {
				result = ProcessResultConstants.STATUS_XSD_PARSE_FAILURE;
				log.error("EcMessageConvertor::convert2EcFlow Unknown xmlcode=>"+xmlobj.toString());
			}
		}catch(Exception e){
			result = ProcessResultConstants.STATUS_XSD_PARSE_FAILURE;
			log.error("EcMessageConvertor::convert2EcFlow error=>"+e.toString());
		}
		return result;
	}
	
	public int convert2EcFlowRespMessageBody(XmlObject xmlobj,EcFlowRespMessageBody messageBody) throws Exception {
		int result = ProcessResultConstants.STATUS_SUCCESS;
		try{
			if (ECFlow201ResponseDocument.class.isInstance(xmlobj)) {
				ECFlow201ResponseDocument ecFlow201RespDocument = (ECFlow201ResponseDocument) xmlobj;
				ECFlow201Response ecFlow201Resp = ecFlow201RespDocument.getECFlow201Response();
				if(ecFlow201Resp.getResponseHead()!=null){
					ECFlowResponseHead ecFlowResponseHead = messageBody.new ECFlowResponseHead();
					ecFlowResponseHead.setMessageId(ecFlow201Resp.getResponseHead().getMessageId());
					ecFlowResponseHead.setRequestMessageId(ecFlow201Resp.getResponseHead().getRequestMessageId());
					ecFlowResponseHead.setBpNo(ecFlow201Resp.getResponseHead().getBpNo());
					ecFlowResponseHead.setTaskId(ecFlow201Resp.getResponseHead().getTaskId());
					ecFlowResponseHead.setCorpTaskId(ecFlow201Resp.getResponseHead().getCorpTaskId());
					ecFlowResponseHead.setResultCode(ecFlow201Resp.getResponseHead().getResultCode());
					ecFlowResponseHead.setResultValue(ecFlow201Resp.getResponseHead().getResultValue());
					ecFlowResponseHead.setResultCode(ecFlow201Resp.getResponseHead().getResultNote());
					messageBody.setEcFlowResponseHead(ecFlowResponseHead);
				}
				if (ecFlow201Resp.getResponseList() != null) {
					ActionResult[] actionRelultArray = ecFlow201Resp.getResponseList().getActionResultArray();
					int len = actionRelultArray.length;
					ActionResult actionResult = null;
					ResponseActionResult responseActionResult = null;
					if(len>0){
						for(int i=0;i<len;i++){
							actionResult = actionRelultArray[i];
							responseActionResult= messageBody.new ResponseActionResult();
							responseActionResult.setActionId(actionResult.getActionId());
							responseActionResult.setResultCode(actionResult.getResultCode());
							responseActionResult.setResultValue(actionResult.getResultValue());
							messageBody.getActionResultList().add(responseActionResult);
						}
					}
				}
			}else {
				result = ProcessResultConstants.STATUS_XSD_PARSE_FAILURE;
				log.error("EcMessageConvertor::convert2EcFlow Unknown xmlcode=>"+xmlobj.toString());
			}
		}catch(Exception e){
			result = ProcessResultConstants.STATUS_XSD_PARSE_FAILURE;
			log.error("EcMessageConvertor::convert2EcFlow error=>"+e.toString());
		}
		return result;
	}
	
	public String convert2StringXml(Object obj){
		String result = null;
		try{
			if(obj instanceof EcFlowMessage){
				EcFlowMessage ecMessage = (EcFlowMessage)obj;
				EC101MessageDocument ec101MessageDocument = EC101MessageDocument.Factory
				.newInstance();
				EC101Message ec101Message = ec101MessageDocument
						.addNewEC101Message();			
				MessageHead messageHead = ec101Message
						.addNewMessageHead();
				messageHead.setMessageId(ecMessage.getFlowMessageHead().getMessageId());
				messageHead.setMessageType(ecMessage.getFlowMessageHead().getMessageType());
				messageHead.setMessageTime(DateUtil.getCurTime());
				messageHead.setSenderId(ecMessage.getFlowMessageHead().getSenderId());
				messageHead.setSenderAddress(ecMessage.getFlowMessageHead().getSenderAddress());
				messageHead.setReceiverId(ecMessage.getFlowMessageHead().getReceiverId());
				messageHead.setReceiverAddress(ecMessage.getFlowMessageHead().getReceiverAddress());
				ECFlow201Document ecFlow201Document = ECFlow201Document.Factory.newInstance();
				ECFlow201 ecFlow201 = ecFlow201Document.addNewECFlow201();
				ECUserType ecUser = ecFlow201.addNewECUser();
				ecUser.setUserId(ecMessage.getFlowMessageBody().getUserId());
				ECFlowType ecFlow = ecFlow201.addNewECFlow();
				ecFlow.setTaskId(ecMessage.getFlowMessageBody().getTaskId());
				ecFlow.setBpNo(ecMessage.getFlowMessageBody().getFlowId());
				ecFlow.setCorpTaskId(ecMessage.getFlowMessageBody().getCorpTaskId());
				ecFlow.setMessageId(ecMessage.getFlowMessageBody().getTaskId());
				ecFlow.setTaskNote(ecMessage.getFlowMessageBody().getTaskNote());			
				ActionList actionList = ecFlow.addNewActionList();
				actionList.addActionId(ecMessage.getFlowMessageBody().getActivityIdList().get(0));
				ECDataType ecData = ecFlow201.addNewECData();									
				ecData.set(ecMessage.getFlowMessageBody().getEcData());
				ec101Message.setMessageBody(XMLDATA.Factory.parse(ecFlow201Document.toString()));
				result = ec101MessageDocument.toString();
			}else if(obj instanceof EcFlowRespMessage){
				EcFlowRespMessage flowRespMessage = (EcFlowRespMessage)obj;
				EC101MessageDocument ec101MessageDocument = EC101MessageDocument.Factory
				.newInstance();
				EC101Message ec101Message = ec101MessageDocument.addNewEC101Message();			
				MessageHead messageHead = ec101Message.addNewMessageHead();
				messageHead.setMessageId(flowRespMessage.getFlowRespMessageHead().getMessageId());
				messageHead.setMessageType(flowRespMessage.getFlowRespMessageHead().getMessageType());
				messageHead.setMessageTime(flowRespMessage.getFlowRespMessageHead().getMessageTime());
				messageHead.setSenderId(flowRespMessage.getFlowRespMessageHead().getSenderId());
				messageHead.setSenderAddress(flowRespMessage.getFlowRespMessageHead().getSenderAddress());
				messageHead.setReceiverId(flowRespMessage.getFlowRespMessageHead().getReceiverId());
				messageHead.setReceiverAddress(flowRespMessage.getFlowRespMessageHead().getReceiverAddress());
				ECFlow201ResponseDocument ecFlow201ResponseDocument = ECFlow201ResponseDocument.Factory.newInstance();
				ECFlow201Response  ecFlow201Response = ecFlow201ResponseDocument.addNewECFlow201Response();
				ResponseHead responseHead = ecFlow201Response.addNewResponseHead();
				responseHead.setMessageId(flowRespMessage.getFlowRespMessageBody().getEcFlowResponseHead().getMessageId());
				responseHead.setRequestMessageId(flowRespMessage.getFlowRespMessageBody().getEcFlowResponseHead().getRequestMessageId());
				responseHead.setBpNo(flowRespMessage.getFlowRespMessageBody().getEcFlowResponseHead().getBpNo());
				responseHead.setTaskId(flowRespMessage.getFlowRespMessageBody().getEcFlowResponseHead().getTaskId());
				responseHead.setCorpTaskId(flowRespMessage.getFlowRespMessageBody().getEcFlowResponseHead().getCorpTaskId());
				responseHead.setResultCode(flowRespMessage.getFlowRespMessageBody().getEcFlowResponseHead().getResultCode());
				responseHead.setResultValue(flowRespMessage.getFlowRespMessageBody().getEcFlowResponseHead().getResultValue());
				ResponseList ecFlow201ResponseList = ecFlow201Response.addNewResponseList();
				List<ResponseActionResult> actionResultList = flowRespMessage.getFlowRespMessageBody().getActionResultList();
				if(actionResultList!=null){
//					ResponseActionResult responseActionResult = actionResultList.get(0);
					for(ResponseActionResult responseActionResult:actionResultList){
						ActionResult ecFlow201ResponseActionResult = ecFlow201ResponseList.addNewActionResult();
						ecFlow201ResponseActionResult.setActionId(responseActionResult.getActionId());
						ecFlow201ResponseActionResult.setResultCode(responseActionResult.getResultCode());
						ecFlow201ResponseActionResult.setResultValue(responseActionResult.getResultValue());
					}
				}
				ec101Message.setMessageBody(XMLDATA.Factory.parse(ecFlow201ResponseDocument.toString()));
				result = ec101MessageDocument.toString();
			}
		}catch(Exception e){
			log.error("EcMessageConvertor::convert2StringXml error=>"+e.toString());
		}
		return result;
	}
	
	public int xsdValidate(String xml){
		int result = ProcessResultConstants.STATUS_SUCCESS;
		String ecflow = null;
		EC101MessageDocument ecmessagedoc = null;
		try{
			ecmessagedoc = EC101MessageDocument.Factory.parse(xml);
			ecflow = ecmessagedoc.getEC101Message().getMessageBody()
					.xmlText().toString();
			XmlObject catdoc = XmlObject.Factory.parse(ecflow);
			if (ECFlow201Document.class.isInstance(catdoc)) {
				ECFlow201Document ecFlow201Document = (ECFlow201Document) catdoc;
				ECFlow201 ecFlow201 = ecFlow201Document.getECFlow201();
				if(ecFlow201.getECFlow().getMessageId()==null){
					ecFlow201.getECFlow().setMessageId(ecFlow201.getECFlow().getTaskId());
				}			
			}
			ArrayList<XmlValidationError> validationErrors = new ArrayList<XmlValidationError>();
			XmlOptions m_validationOptions = new XmlOptions();
			m_validationOptions.setErrorListener(validationErrors);
			boolean ff = catdoc.validate(m_validationOptions);
			log.debug("Flow Validater :" + ff);
			if (!ff) {
				String errMsg = printErrors(validationErrors);
				log.error("FLOW XSD Validate　Error:" + errMsg);
				result = ProcessResultConstants.STATUS_XSD_VALID_FAILURE;
			}
		}catch(Exception e){
			log.error("Flow xsdValidate error=>"+e.toString());
			result = ProcessResultConstants.STATUS_XSD_VALID_FAILURE;
		}
		return result;
	}

	private String printErrors(ArrayList<XmlValidationError> validationErrors) {
		String errMsg = SimpleConstants.RESPONSE_MSG_VALIDATER + "\n";
		log.error("Errors discovered during validation: \n");
		Iterator<XmlValidationError> iter = validationErrors.iterator();
		while (iter.hasNext()) {
			XmlValidationError xe = iter.next();
			log.error(">> " + xe + "\n");
			errMsg = errMsg + xe.getMessage() + "\n";
		}
		return errMsg;
	}

//	public int convert2EcFlow(byte[] xml, String encoding,EcFlowMessageBody messageBody)
//			throws Exception {
//		return this.convert2EcFlowMessageBody(new String(xml, encoding),messageBody);
//	}

	public byte[] convert2Xml(Object obj) throws Exception {
		return null;
	}

}
